package com.seleniti.enpareja.controller.ui.view;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.ioc.commons.flowcontrol.actioncontroller.ActionController;
import org.ioc.commons.flowcontrol.actioncontroller.ActionHandler;
import org.ioc.commons.flowcontrol.common.impl.ReceiverAdapter;
import org.ioc.commons.flowcontrol.eventbus.EventBus;
import org.ioc.commons.flowcontrol.logincontroller.IsLoggedUserInfoConsumer;
import org.ioc.commons.flowcontrol.operationmanager.OperationManager;
import org.ioc.commons.flowcontrol.operationmanager.impl.OperationHandlerFactory;
import org.ioc.commons.model.globaldata.GlobalDataController.Consumer;
import org.ioc.commons.model.globaldata.IsGlobalDataConsumer;
import org.ioc.commons.utils.Format;
import org.ioc.commons.utils.FormatterLogger;

import com.seleniti.enpareja.controller.common.GlobalData;
import com.seleniti.enpareja.controller.common.domain.LoggedUserInfo;
import com.seleniti.enpareja.controller.model.integration.database.domain.Couple;
import com.seleniti.enpareja.controller.model.integration.database.domain.CoupleType;
import com.seleniti.enpareja.controller.model.integration.database.domain.WorkShift;
import com.seleniti.enpareja.controller.model.integration.service.WorkShiftService;
import com.seleniti.enpareja.controller.ui.base.EnParejaViewBasePresenter;
import com.seleniti.enpareja.controller.ui.main.AppShell;
import com.seleniti.enpareja.controller.ui.view.WorkShiftsView.Action;
import com.seleniti.enpareja.controller.ui.view.WorkShiftsView.ActionMode;
import com.seleniti.enpareja.controller.ui.view.WorkShiftsView.Board;
import com.seleniti.enpareja.controller.ui.view.WorkShiftsView.Event;
import com.seleniti.enpareja.controller.ui.view.WorkShiftsView.Operation;

/**
 * Presenter for the Login view
 * 
 * @author Jesús Lunar Pérez
 * 
 */
public class WorkShiftsViewPresenter
		extends
		EnParejaViewBasePresenter<WorkShiftsView, WorkShiftsView.Event, WorkShiftsView.Operation, WorkShiftsView.Action>
		implements WorkShiftsView.Presenter, IsLoggedUserInfoConsumer<LoggedUserInfo>, IsGlobalDataConsumer<GlobalData> {

	private static final FormatterLogger logger = FormatterLogger.getLogger(WorkShiftsViewPresenter.class);
	private WorkShiftService workshiftservice;
	private Consumer<GlobalData> consumer;

	public WorkShiftsViewPresenter(WorkShiftsView display, EventBus<Event> eventbus,
			OperationManager<Operation> operationManager, ActionController<Action> actionController) {
		super(display, eventbus, operationManager, actionController);
	}

	@Override
	public void onInitDisplay() {
		super.onInitDisplay();
		this.consumer = this.globalDataController.registerGlobalDataConsumer(this);
		
		this.workshiftservice = serviceManager.serviceFactory().workShiftService();
		display.setActionMode(ActionMode.MODIFY_ELEMENT);
		this.consumer.requires(GlobalData.UserAgent);
		this.loginController.requiresLoggedUserInfoIfDisplayActive(this);
	}

	@Override
	protected void bindComponents() {
		super.bindComponents();
		operationManager.bindOperationsRunning(OperationHandlerFactory.<Operation> forLoaders(display));
		operationManager.bindOperationsRunning(OperationHandlerFactory.<Operation> forLoaders(shell.globalLoader()));

		shell.actionController().bindAction(AppShell.Action.DeleteNow, new ActionHandler<AppShell.Action>() {

			@Override
			public void handleAction(Object sender, com.seleniti.enpareja.controller.ui.main.AppShell.Action action,
					Object... params) {
				deleteSelected();
			}
		});
	}

	protected void deleteSelected() {
		if (display.getActionMode() == ActionMode.DELETE_ELEMENT) {
			Set<WorkShift> selection = display.getSelection();

			this.workshiftservice.deleteAll(selection).performing(Operation.Deleting, operationManager).caller(this)
					.to(new ReceiverAdapter<Void>() {

						@Override
						public void success(Void result) {
							refreshData();
						}
					});

			display.setActionMode(ActionMode.MODIFY_ELEMENT);
		}

	}

	@SuppressWarnings("deprecation")
	@Override
	public void onActive() {
		super.onActive();

		Date oneDayBefore = new Date();
		Date tenDaysLater = new Date();
		oneDayBefore.setDate(oneDayBefore.getDate() - 1);
		tenDaysLater.setDate(tenDaysLater.getDate() + 10);

		display.filterFromDate().setValue(oneDayBefore);
		display.filterToDate().setValue(tenDaysLater);

		refreshData();

		shell.refreshButtonVisibility().setVisible(true);

		LoggedUserInfo lui = this.loginController.getLoggedUserInfo();

		display.setEnabled(lui != null && lui.getCoupleName() != null && !lui.getCoupleName().isEmpty());

		shell.nonAssociatedPanelVisibility().setVisible(
				lui != null && lui.isLogged() && (lui.getCoupleName() == null || lui.getCoupleName().isEmpty() || lui.getCoupleType()==CoupleType.TESTING_MODE_COUPLE));
		
		shell.firstStepsVisibility().setVisible(shell.nonAssociatedPanelVisibility().isVisible() && lui.getCoupleType()!=CoupleType.TESTING_MODE_COUPLE);
		shell.nonAssociatedButtonVisibility().setVisible(!shell.firstStepsVisibility().isVisible());

		this.consumer.ensureRequirements();
	}

	@Override
	public void onRequiredGlobalDataReady() {
		showGoBackButtonIfRequired();
	}

	@Override
	public void onRequiredGlobalDataNotReadyYet() {
		/*
		 * Nothing to do
		 */
	}

	@Override
	public void onRequiredGlobalDataUpdated(GlobalData globalDataUpdated) {
		showGoBackButtonIfRequired();
	}

	@Override
	protected void refreshData() {
		super.refreshCouple(new ReceiverAdapter<Couple>() {

			@Override
			public void success(Couple result) {
				display.member1Name().setValue(
						result != null && result.getMember1() != null && result.getMember1().getNickName() != null
								&& !result.getMember1().getNickName().isEmpty() ? result.getMember1().getNickName()
								: "Tú");
				display.member2Name().setValue(
						result != null && result.getMember2() != null && result.getMember2().getNickName() != null
								&& !result.getMember2().getNickName().isEmpty() ? result.getMember2().getNickName()
								: "Tu pareja");
				
				display.member1ActionsVisible().setVisible(
						result != null && result.getMember1() != null && !result.getMember1().isFakeUser());
				display.member2ActionsVisible().setVisible(
						result != null && result.getMember2() != null && !result.getMember2().isFakeUser());

			}
		}, Operation.GettingData, operationManager, "member1", "member2");

		Date fromDate = display.filterFromDate().getValue();
		Date toDate = display.filterToDate().getValue();
		if (fromDate != null && toDate != null) {
			this.workshiftservice.getList(fromDate, toDate, true).performing(Operation.GettingData, operationManager)
					.caller(this).to(new ReceiverAdapter<List<WorkShift>>() {

						@Override
						public void success(List<WorkShift> result) {
							display.workshiftList().clear();
							if (result != null) {
								logger.debug("Dates got: {0}",
										Format.collectionToString(result, new Format.StringFormatter<WorkShift>() {

											@Override
											public String asString(WorkShift obj) {
												return obj != null ? String.valueOf(obj.getDate()) : null;
											}
										}));

								display.workshiftList().addAll(result);
							}
						}
					});
		} else {
			display.workshiftList().clear();
		}

	}

	@Override
	public void onLoggedUserInfoDataReady() {
		refreshData();
	}

	@Override
	public void onLoggedUserInfoDataUpdated(LoggedUserInfo loggedUserInfo) {
	}

	@Override
	public void onLoggedUserInfoNotReadyYet() {
	}

	@Override
	public void onActionModeChanged() {
		ActionMode mode = display.getActionMode();

		logger.info("Action mode changed: {0}", mode);

		switch (mode) {
		case DELETE_ELEMENT:
			this.shell.deleteButtonVisibility().setVisible(true);
			break;
		default:
			this.shell.deleteButtonVisibility().setVisible(false);
		}

	}

	@Override
	public void onSelectionChanged() {
		ActionMode mode = display.getActionMode();

		logger.info("Selection changed on mode {0}", mode);

		if (mode == ActionMode.MODIFY_ELEMENT) {
			Set<WorkShift> selection = display.getSelection();

			if (!selection.isEmpty()) {
				final WorkShift single = selection.iterator().next();
				display.showModifyForm(single);
			}
		}

	}

	@Override
	public void onWorkShiftModified() {
		if (display.date().getValue() != null) {
			display.hideModificationForm();

			this.workshiftservice
					.createOrReplace(display.date().getValue(), display.shiftMember1().getValue(),
							display.shiftMember2().getValue(), display.commentMember1().getValue(),
							display.commentMember2().getValue()).performing(Operation.Saving, operationManager)
					.caller(this).to(new ReceiverAdapter<Void>() {

						@Override
						public void success(Void result) {
							refreshData();
						}
					});

		} else {
			messageBoxFactory.alert("Decidir comida", "Debes poner una fecha");
		}
	}

	@Override
	public void onFilteDateChanged() {
		refreshData();
	}

	@Override
	public boolean onGoBoardBack() {
		if (this.display.boardShown().getValue() != Board.MAIN_LIST) {
			this.display.boardShown().setValue(Board.MAIN_LIST);
			return true;
		}

		return false;
	}
}
